#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>

#include "linux-input.h"
#include "config.h"
#include "rotate_daemon.h"

static int X_THRESHOLD = 40;
static int Y_THRESHOLD = 40;

static int current_x = 0;
static int current_y = 0;

enum rotation_mode {
	ROTATION_X_HIGH,
	ROTATION_X_LOW,
	ROTATION_Y_HIGH,
	ROTATION_Y_LOW
};
static int ROTATION_NORMAL = ROTATION_Y_LOW;
static int current_rotation = ROTATION_Y_LOW;

int device_open(int nr, int verbose)
{
	char filename[32];
	int fd, version;

	snprintf(filename,sizeof(filename),
	         "/dev/input/event%d",nr);
	fd = open(filename,O_RDONLY);
	if (-1 == fd) {
		fprintf(stderr,"open %s: %s\n",
			filename,strerror(errno));
		return -1;
	}
	if (verbose)
		fprintf(stderr,"%s\n",filename);

	if (-1 == ioctl(fd,EVIOCGVERSION,&version)) {
		perror("ioctl EVIOCGVERSION");
		close(fd);
		return -1;
	}
	if (EV_VERSION != version) {
		fprintf(stderr, "protocol version mismatch (expected %d, got %d)\n",
			EV_VERSION, version);
		close(fd);
		return -1;
	}
	return fd;
}

void handle_accel_event(struct input_event *event)
{
        char ts[32];
        time_t t;
	int new_rotation = current_rotation;

        switch (event->type) {
        case EV_ABS:
                fprintf(stdout," code=%u value=%d\n",
			(unsigned int)event->code, event->value);
		if(event->code == 0) {
			current_x = event->value;
		} else if(event->code == 1) {
			current_y = event->value;
		}
		int rotated = 0;
		if(current_x > X_THRESHOLD) {
			new_rotation = ROTATION_X_HIGH;
		}else if(current_x < -X_THRESHOLD) {
			new_rotation = ROTATION_X_LOW;
		}else if(current_y < -Y_THRESHOLD) {
			new_rotation = ROTATION_Y_LOW;
		}else if(current_y > Y_THRESHOLD) {
			new_rotation = ROTATION_Y_HIGH;
		}
		if(new_rotation != current_rotation) {
			char script[256];
			switch(new_rotation) {
			case ROTATION_X_HIGH:
				snprintf(script,sizeof(script),
					"%s %s", ROTATE_SCRIPT, "x_high"); 
				fprintf(stdout, "executing: %s", script);
				system(script);
				break;
			case ROTATION_X_LOW:
				snprintf(script,sizeof(script),
					"%s %s", ROTATE_SCRIPT, "x_low");
				fprintf(stdout, "executing: %s", script);
				system(script);
				break;
			case ROTATION_Y_HIGH:
				snprintf(script,sizeof(script),
					"%s %s", ROTATE_SCRIPT, "y_high");
				fprintf(stdout, "executing: %s", script);
				system(script);
				break;
			case ROTATION_Y_LOW:
				snprintf(script,sizeof(script),
					"%s %s", ROTATE_SCRIPT, "y_low");
				fprintf(stdout, "executing: %s", script);
				system(script);
				break;
			default:
				snprintf(script,sizeof(script),
					"%s %s", ROTATE_SCRIPT, "x_high");
				fprintf(stdout, "executing: %s", script);
				system(script);
				break;
			};
			current_rotation = new_rotation;
		}
                break;
        }
}

int is_acceleration_sensor(int fd)
{
        struct input_id id;
        BITFIELD bits[32];
        char buf[32];
        int rc,bit;

        rc = ioctl(fd,EVIOCGID,&id);
	if (id.vendor == 0x1014 && id.product == 0x5054) {
		return 1;
	} else {
		return 0;
	}
}

static void process_events(int fd)
{
	int timeout = 10;
	struct input_event event;
	struct timeval tv;
	int quit;
	fd_set set;

	fprintf(stderr,"waiting for events\n");
	quit = 0;
	for (;;) {
		/* wait for input */
		FD_ZERO(&set);
		FD_SET(fd,&set);
		tv.tv_sec  = timeout;
		tv.tv_usec = 0;
		switch (select(fd+1,&set,NULL,NULL,&tv)) {
		case -1:
			perror("select");
			quit = 1;
			break;
		case 0:
			fprintf(stderr,"timeout, quitting\n");
			quit = 1;
			break;
		}
		if (quit)
			break;

		/* read input */
		if (FD_ISSET(fd,&set)) {
			switch (read(fd,&event,sizeof(event))) {
			case -1:
				perror("read");
				quit = 1;
				break;
			case 0:
				fprintf(stderr,"EOF\n");
				quit = 1;
				break;
			default:
				handle_accel_event(&event);
				break;
			}
		}
		if (quit)
			break;
	}
	close(fd);
}

static int find_hdaps_device(void)
{
	int i,fd;

	for (i = 0; i < 32; i++) {
		/* try to open */
		fd = device_open(i,1);
		if(fd != -1 && is_acceleration_sensor(fd)) {
			return fd;
		}
		close(fd);
	}
	return -1;
}

int main(int argc, char *argv[])
{
	int accel_fd = find_hdaps_device();
	if(accel_fd == -1) {
		fprintf(stderr, "No accelerometer device found\n");
		exit(-1);
	}
	process_events(accel_fd);
}

